﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace AudiPyme.DAL
{
    public static class Matriz_AmenazasVulnerabilidadesFactory
    {
        //Inserta una relación amenaza - vulnerabilidad en la base de conocimiento
        public static void InsertarMatriz_AmenazasVulnerabilidades(Matriz_AmenazasVulnerabilidades AmenazaVulnerabilidad)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            agenteBD.AddToMatriz_AmenazasVulnerabilidadesEstablecer(AmenazaVulnerabilidad);
            agenteBD.SaveChanges();
        }

        //Devuelve una relación amenaza - vulnerabilidad a través de los nombres de los elementos que conforman la relación
        public static Matriz_AmenazasVulnerabilidades BuscarMatriz_AmenazasVulnerabilidades(String AmenazaSeleccionada, String VulnerabilidadSeleccionada)
        {
            Matriz_AmenazasVulnerabilidades matriz = new Matriz_AmenazasVulnerabilidades();
            //Recogemos los Id's asociados a la Amenaza y Vulnerabilidad seleccionada
            int IdAmenazaSelec = 0;
            int IdVulnerabilidadSelec = 0;
            ModeloContainer agenteBD = new ModeloContainer();
            IQueryable<int> IdAmenaza = from Amenazas in agenteBD.AmenazasEstablecer
                                        where Amenazas.Amenaza == AmenazaSeleccionada
                                        select Amenazas.IdAmenaza;
            foreach (int a in IdAmenaza)
            {
                IdAmenazaSelec = a;
            }
            IQueryable<int> IdVulnerabilidad = from Vulnerabilidades in agenteBD.VulnerabilidadesEstablecer
                                               where Vulnerabilidades.Vulnerabilidad == VulnerabilidadSeleccionada
                                               select Vulnerabilidades.IdVulnerabilidad;
            foreach (int v in IdVulnerabilidad)
            {
                IdVulnerabilidadSelec = v;
            }
            matriz.IdAmenaza = IdAmenazaSelec;
            matriz.IdVulnerabilidad = IdVulnerabilidadSelec;
            return matriz;
        }

        //Elimina una relación amenaza - vulnerabilidad
        public static void EliminarMatriz_AmenazasVulnerabilidades(Matriz_AmenazasVulnerabilidades matriz)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            IQueryable<Matriz_AmenazasVulnerabilidades> MatrizAmenVuln
                                         = from MAV in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                           where MAV.IdAmenaza == matriz.IdAmenaza &&
                                                 MAV.IdVulnerabilidad == matriz.IdVulnerabilidad
                                           select MAV;
            agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer.DeleteObject(MatrizAmenVuln.First());
            agenteBD.SaveChanges();
        }

        //Método que recoge el número de Relaciones Amenaza - Vulnerabilidad disponibles de la base de conocimiento 
        public static int NumRelacAmenVuln()
        {
            ModeloContainer agenteBD = new ModeloContainer();
            int nRelac = (from RelacTipActVuln in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                          where RelacTipActVuln.Actual == true
                          select RelacTipActVuln).Count();
            return nRelac;
        }

        //Método que elimina (borrado lógico) una relación Amenaza - Vulnerabilidad de la base de conocimiento
        public static void EliminarAmenVuln(int IdAmenaza, int IdVulnerabilidad)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            Matriz_AmenazasVulnerabilidades nuevaRelacion =
                new Matriz_AmenazasVulnerabilidades();
            nuevaRelacion.IdAmenaza = IdAmenaza;
            nuevaRelacion.IdVulnerabilidad = IdVulnerabilidad;
            Matriz_AmenazasVulnerabilidades RelacionEliminar
                        = (from RelMatriz in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                           where RelMatriz.IdAmenaza == nuevaRelacion.IdAmenaza &&
                                 RelMatriz.IdVulnerabilidad == nuevaRelacion.IdVulnerabilidad
                           select RelMatriz).First();
            //Seteamos el valor Actual a false
            RelacionEliminar.Actual = false;
            agenteBD.SaveChanges();
        }

        //Método que hace un borrado lógico de todas las relaciones amenazas - vulnerabilidad dependientes de una lista de Amenazas
        public static List<Matriz_AmenazasVulnerabilidades> EliminaRelacionesPorAmenaza(List<Amenazas> LAmenazas)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada amenaza de la lista
            //Lista de aquellas relaciones a las que se le hacen un borrado lógico
            List<Matriz_AmenazasVulnerabilidades> LRelacionesEliminadas = new List<Matriz_AmenazasVulnerabilidades>();
            foreach (Amenazas A in LAmenazas)
            {
                //Recogemos las Relaciones actuales de la Matriz
                IQueryable<Matriz_AmenazasVulnerabilidades> RelacTipActAmenCrit = from Relac in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                                  where Relac.IdAmenaza == A.IdAmenaza && Relac.Actual == true
                                                                                  select Relac;
                if (RelacTipActAmenCrit.Count() != 0)
                {
                    //Para cada uno actualizamos el Valor Actual a false
                    foreach (Matriz_AmenazasVulnerabilidades Relacion in RelacTipActAmenCrit)
                    {
                        Relacion.Actual = false;
                        //Añadimos a la lista de Relaciones Eliminadas
                        LRelacionesEliminadas.Add(Relacion);
                    }
                }
            }
            agenteBD.SaveChanges();
            return LRelacionesEliminadas;
        }

        //Método que elimina (borrado lógico) y devuelve una lista de las relaciones amenazas - vulnerabilidades que hay en la base de conocimiento
        //asociadas a una vulnerabilidad dada
        internal static List<Matriz_AmenazasVulnerabilidades> EliminaRelacionesPorVulnerabilidad(int IdVulnerabilidad)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Recogemos las relaciones actuales en la Base de Conocimiento
            List<Matriz_AmenazasVulnerabilidades> LAmenVuln = new List<Matriz_AmenazasVulnerabilidades>();
            IQueryable<Matriz_AmenazasVulnerabilidades> RelTipActAmenCrit = from Rel in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                            where Rel.IdVulnerabilidad == IdVulnerabilidad && Rel.Actual == true
                                                                            select Rel;
            if (RelTipActAmenCrit.Count() != 0)
            {
                //Para cada uno actualizamos el Valor Actual a false
                foreach (Matriz_AmenazasVulnerabilidades R in RelTipActAmenCrit)
                {
                    R.Actual = false;
                    LAmenVuln.Add(R);
                }
                agenteBD.SaveChanges();
            }
            //Si no había Relaciones dependientes devolvemos la fila vacía
            return LAmenVuln;
        }

        //Método que restaura y devuelve una lista de las relaciones amenazas - vulnerabilidades de la base de conocimiento
        //asociadas a una lista de amenazas
        internal static List<Matriz_AmenazasVulnerabilidades> RestauraRelacionesPorAmenaza(List<int> LAmenazas)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada amenaza de la lista
            //Lista de aquellas relaciones a las que se le hacen un borrado lógico
            List<Matriz_AmenazasVulnerabilidades> LRelacionesRestauradas = new List<Matriz_AmenazasVulnerabilidades>();
            foreach (int IdAmenaza in LAmenazas)
            {
                //Recogemos las Relaciones actuales de la Matriz
                IQueryable<Matriz_AmenazasVulnerabilidades> RelacTipActAmenCrit = from Relac in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                                  where Relac.IdAmenaza == IdAmenaza
                                                                                  select Relac;
                if (RelacTipActAmenCrit.Count() != 0)
                {
                    //Para cada uno actualizamos el Valor Actual a True
                    foreach (Matriz_AmenazasVulnerabilidades Relacion in RelacTipActAmenCrit)
                    {
                        Relacion.Actual = true;
                        //Añadimos a la lista de Relaciones Restauradas
                        LRelacionesRestauradas.Add(Relacion);
                    }
                }
            }
            agenteBD.SaveChanges();
            return LRelacionesRestauradas;
        }


        //Método que restaura las relaciones a partir de una lista de Ids de Vulnerabilidades
        internal static List<Matriz_AmenazasVulnerabilidades> RestauraRelacionesPorVulnerabilidad(List<int> LVulnerabilidades)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada criterio de riesgo de la lista
            //Lista de aquellas relaciones a las que se le hacen un borrado lógico
            List<Matriz_AmenazasVulnerabilidades> LRelacionesRestauradas = new List<Matriz_AmenazasVulnerabilidades>();
            foreach (int IdVulnerabilidad in LVulnerabilidades)
            {
                //Recogemos las Relaciones actuales de la Matriz
                IQueryable<Matriz_AmenazasVulnerabilidades> RelacTipActVuln = from Relac in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                              where Relac.IdVulnerabilidad == IdVulnerabilidad
                                                                              select Relac;
                if (RelacTipActVuln.Count() != 0)
                {
                    //Para cada uno actualizamos el Valor Actual a True
                    foreach (Matriz_AmenazasVulnerabilidades Relacion in RelacTipActVuln)
                    {
                        Relacion.Actual = true;
                        //Añadimos a la lista de Relaciones Eliminadas
                        LRelacionesRestauradas.Add(Relacion);
                    }
                }
            }
            agenteBD.SaveChanges();
            return LRelacionesRestauradas;
        }

        //Método que Inserta una Relación Amenaza Vulnerabilidad 
        public static void Inserta_Relacion_Amenaza_Vulnerabilidad(string AmenazaSelec, string VulnerabilidadSelec)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            Matriz_AmenazasVulnerabilidades matriz = new Matriz_AmenazasVulnerabilidades();
            //Recogemos los Id's asociados a la Amenaza y la Vulnerabilidad seleccionados
            int IdAmenazaSelec = AmenazasFactory.BuscarIdAmenaza(AmenazaSelec);
            int IdVulnerabSelec = VulnerabilidadesFactory.IdVulnerabilidad(VulnerabilidadSelec);
            IQueryable<Matriz_AmenazasVulnerabilidades> Relacion = from Matriz in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                   where Matriz.IdAmenaza == IdAmenazaSelec && Matriz.IdVulnerabilidad == IdVulnerabSelec
                                                                   select Matriz;
            //Si la relacion no existe en la base de datos
            if (Relacion.Count() == 0)
            {
                //se inserta
                Matriz_AmenazasVulnerabilidades nuevaRelacion = new Matriz_AmenazasVulnerabilidades();
                nuevaRelacion.IdAmenaza = IdAmenazaSelec;
                nuevaRelacion.IdVulnerabilidad = IdVulnerabSelec;
                nuevaRelacion.Actual = true;
                InsertarMatriz_AmenazasVulnerabilidades(nuevaRelacion);
            }
            //Si existe se actualiza su valor Actual a true
            else
            {
                Relacion.First().Actual = true;
                agenteBD.SaveChanges();
            }

        }

        //Método que restaura una relación amenaza - vulnerabilidad de la base de conocimiento
        public static void RestauraConocimientoPorRelacion(List<Matriz_AmenazasVulnerabilidades> LAmenazasVulnerabilidades)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Lista de IdsAmenazas e IdTiposAmenazas asociadas
            List<int> LIdsAmenazas = new List<int>();
            List<int> LIdsTipoAmenazas = new List<int>();
            List<int> LIdsVulnerabilidades = new List<int>();
            //Recorremos las relaciones seleccionadas 
            foreach (Matriz_AmenazasVulnerabilidades Relacion in LAmenazasVulnerabilidades)
            {
                Matriz_AmenazasVulnerabilidades RelacionRestaura = (from MatrizAmenContr in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                    where MatrizAmenContr.IdAmenaza == Relacion.IdAmenaza &&
                                                                          MatrizAmenContr.IdVulnerabilidad == Relacion.IdVulnerabilidad
                                                                    select MatrizAmenContr).Single();
                RelacionRestaura.Actual = true;
                //Recogemos los Ids distintos de Amenazas y Tipos de Amenazas asociadas de las relaciones
                if (!LIdsAmenazas.Contains(Relacion.IdAmenaza))
                    LIdsAmenazas.Add(Relacion.IdAmenaza);
                int IdTipoAmenaza = TiposAmenazasFactory.IdTipoAmenaza(Relacion.IdAmenaza);
                if (!LIdsTipoAmenazas.Contains(IdTipoAmenaza))
                    LIdsTipoAmenazas.Add(IdTipoAmenaza);
                //Recogemos los Ids distintos de Vulnerabilidades
                if (!LIdsVulnerabilidades.Contains(Relacion.IdVulnerabilidad))
                    LIdsVulnerabilidades.Add(Relacion.IdVulnerabilidad);
            }

            //Restauramos las Amenazas y Tipos de Amenazas recogidas a través de sus Ids
            AmenazasFactory.RestauraAmenazaPorRelaciones(LIdsAmenazas);
            TiposAmenazasFactory.RestauraTipoAmenazaPorRelaciones(LIdsTipoAmenazas);
            VulnerabilidadesFactory.RestauraVulnerabilidadPorRelaciones(LIdsVulnerabilidades);
            agenteBD.SaveChanges();
        }


        //Método que devuelve si una relación amenaza - vulnerabilidad está en la base de datos
        public static bool EstaRelacion_Amenaza_Vulnerabilidad(string AmenazaSelec, string VulnerabilidadSelec)
        {
            bool esta = false;
            ModeloContainer agenteBD = new ModeloContainer();
            int IdAmenazaSelec = AmenazasFactory.BuscarIdAmenaza(AmenazaSelec);
            int IdVulnerabilidadSelec = VulnerabilidadesFactory.IdVulnerabilidad(VulnerabilidadSelec);
            IQueryable<Matriz_AmenazasVulnerabilidades> RelacionEncontrada = from MatrAmenContr in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer
                                                                             where MatrAmenContr.IdAmenaza == IdAmenazaSelec && MatrAmenContr.IdVulnerabilidad == IdVulnerabilidadSelec
                                                                             select MatrAmenContr;
            //Si está la relación y con el campo actual a true se devuelve un true
            if (RelacionEncontrada.Count() != 0 && RelacionEncontrada.First().Actual == true)
            {
                esta = true;
            }
            return esta;
        }
    }
}
